//
// Created by chnlich on 6/27/15.
//

#include "database_interface.h"
#include "atomic_lib.h"

int32_t db_manage_init() {
	int32_t i;
	for (i = 0; i < MAX_SUPPORT_DB; i++)
		used[i] = 0;
	int32_t tmp = 1;
	int32_t ret = pthread_mutex_init(&dispatch, (const pthread_mutexattr_t *) &tmp);
	if (ret != 0)
		return ret;
	return 0;
}

static int32_t use_empty_db() {
	pthread_mutex_lock(&dispatch);
	int32_t i;
	for (i = 0; i < MAX_SUPPORT_DB; i++)
		if (!used[i])
			break;
	if (i == MAX_SUPPORT_DB)
		i = -1;
	else
		used[i] = 1;
	pthread_mutex_unlock(&dispatch);
	return i;
}

int32_t db_create_db(int32_t key_length, int32_t value_length) {
	int32_t i = use_empty_db();
	if (i >= 0) {
		int32_t ret = database_init(db_list + i, key_length, value_length);
		if (ret != 0)
			return ret;
	}
	return i;
}

int32_t db_close_db(int32_t db_id) {
	pthread_mutex_lock(&dispatch);
	uint32_t ret = 0;
	if (used[db_id]) {
		database_close(&db_list[db_id]);
		used[db_id] = 0;
	}
	else
		ret = -1;
	pthread_mutex_unlock(&dispatch);
	return ret;
}

int32_t db_insert_data(int32_t db_id, struct database_item *d) {
	if (!used[db_id])
		return -1;
	return database_insert(&db_list[db_id], d);
}

int32_t db_delete_data(int32_t db_id, cond_func f) {
	if (!used[db_id])
		return -1;
	return database_delete(&db_list[db_id], f);
}

int32_t db_delete_data_from_key(int32_t db_id, struct database_keypair *key) {
	if (!used[db_id])
		return -1;
	return database_delete_from_key(&db_list[db_id], key);
}

int32_t db_query_data(int32_t db_id, cond_func f, struct database_item_list **ret) {
	if (!used[db_id])
		return -1;
	int32_t r = database_search(&db_list[db_id], f, ret);
	if (r < 0) {
		*ret = NULL;
		return r;
	}
	struct database_item_list *cur = *ret;
	for (; cur; cur = cur->next)
		set_database_item(&cur->dbi, cur->dbi.key, cur->dbi.value, db_list[db_id].key_length,
		                  db_list[db_id].value_length);

	return 0;
}

int32_t db_query_data_from_key(int32_t db_id, struct database_keypair *key, struct database_item_list **ret) {
	if (!used[db_id])
		return -1;
	int32_t r = database_search_from_key(&db_list[db_id], key, ret);
	if (r < 0) {
		*ret = NULL;
		return r;
	}
	struct database_item_list *cur = *ret;
	for (; cur; cur = cur->next)
		set_database_item(&cur->dbi, cur->dbi.key, cur->dbi.value, db_list[db_id].key_length,
		                  db_list[db_id].value_length);
	return 0;
}

int32_t db_save(int32_t db_id, const char *file_name) {
	if (!used[db_id])
		return -1;
	return database_save(&db_list[db_id], file_name);
}

int32_t db_load(const char *file_name) {
	int32_t db_id = use_empty_db();
	int32_t ret;
	if (db_id < 0)
		return db_id;
	ret = database_load(&db_list[db_id], file_name);
	if (ret < 0) {
		used[db_id] = 0;
		return ret;
	}
	return db_id;
}
